package com.citywithincity.db.meta.impl;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import com.citywithincity.db.Db;
import com.citywithincity.db.meta.ColumnStruct;
import com.citywithincity.db.meta.DbStructFactory;
import com.citywithincity.db.meta.Snapshot;
import com.citywithincity.db.meta.TableStruct;
import com.citywithincity.utils.IoUtil;
import com.citywithincity.utils.JsonUtil;

public class DefaultSnapshot implements Snapshot {

	@Override
	public void save(int db,File file) throws IOException {
		try{
			Collection<TableStruct> list = Db.getStruct(db).getTableStructs(DbStructFactory.STRUCT_ALL);
			String json = JsonUtil.toJson(list);
			IoUtil.write(file, json);
		}finally{
			Db.release();
		}
	}

	@Override
	public void compare(int db,File src, File desc) throws IOException {
		DbStructFactory struct = Db.getStruct(db);
		//找出本数据库的结构
		Collection<TableStruct> list = struct.getTableStructs(DbStructFactory.STRUCT_ALL);
		Map<String,TableStruct> thisMap = toMap(list);
		Map<String, TableStruct> otherMap = parseFile(src);
		
		//比较thisMap和otherMap的区别
		
		//多出来
		Set<String> thisMore = new HashSet<String>();
		thisMore.addAll(thisMap.keySet());
		thisMore.removeAll(otherMap.keySet());
		//少了
		Set<String> thisLess = new HashSet<String>();
		thisLess.addAll(otherMap.keySet());
		thisLess.removeAll(thisMap.keySet());
		//一样
		Set<String> same = new HashSet<String>();
		same.addAll(thisMap.keySet());
		same.retainAll(otherMap.keySet());

		/**
		 * 对于多出来的表，创建
		 */
		for (String key : thisMore) {
			struct.createTable(thisMap.get(key));
		}

		for (String key : thisLess) {
			
		}
		/**
		 * 对于一样的表,比较不同
		 */
		for (String key : same) {
			
			
			
		}
		
	}
	
	private Map<String,TableStruct> toMap(Collection<TableStruct> list){
		Map<String,TableStruct> tables = new TreeMap<String, TableStruct>();
		for (TableStruct struct : list) {
			tables.put(struct.getName().toUpperCase(), struct);
		}
		return tables;
	}
	
	@SuppressWarnings("unchecked")
	private Map<String,TableStruct> parseFile(File src) throws IOException{
		FileReader reader =null;
		try{
			reader = new FileReader(src);
			Map<String,TableStruct> tables = new TreeMap<String, TableStruct>();
			List<Map<String, Object>> list = JsonUtil.getMapper().readValue(reader, List.class);
			for (Map<String, Object> data : list) {
				List<Map<String, Object>> columns = (List<Map<String, Object>>) data.get("columns");
				String name = (String) data.get("name");
				String comment = (String) data.get("comment");
				TableStruct struct = new TableStruct(parseColumns(columns,name), 
						name, comment);
				tables.put(struct.getName().toUpperCase(), struct);
			}
			return tables;
		}finally{
			IoUtil.close(reader);
		}
		
	}
	
	
	
    // Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean  
    public static void transMap2Bean(Map<String, Object> map, Object obj) throws IntrospectionException {  
  
    	BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  

        for (PropertyDescriptor property : propertyDescriptors) {  
            String key = property.getName();  

            if (map.containsKey(key)) {  
                Object value = map.get(key);  
                // 得到property对应的setter方法  
                Method setter = property.getWriteMethod();  
                try {
					setter.invoke(obj, value);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}  
            }  

        }  
  
    }  
	private List<ColumnStruct> parseColumns(List<Map<String, Object>> columns, String table){
		List<ColumnStruct> result = new ArrayList<ColumnStruct>(columns.size());
		for (Map<String, Object> data : columns) {
			ColumnStruct struct = new ColumnStruct(table);
			try {
				transMap2Bean(data, struct);
			} catch (IntrospectionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			result.add(struct);
		}
		return result;
	}

	@Override
	public void diff(File src, File desc, File output) {
		//比较两份文件
	}

}
